package org.xiaoyu.rpc.client;


import org.xiaoyu.rpc.common.url.URL;
import org.xiaoyu.rpc.remoting.packet.Invocation;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.UUID;

/**
 * Created By Have
 * 2021/7/4 17:32
 */
public class RpcClientProxy implements InvocationHandler {
    private ClientHandler client;
    private URL url;

    public RpcClientProxy(ClientHandler client, URL url) {
        this.client = client;
        this.url = url;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Method[] methods = Object.class.getMethods();
        // TODO dynamic toString stackoverflow
        for (Method m: methods) {
            if (m.getName().equals(method.getName())) {
                return null;
            }
        }
        Invocation rpcRequest = Invocation.builder()
                .serviceName(method.getDeclaringClass().getName())
                .parameters(args)
                .paramTypes(method.getParameterTypes())
                .methodName(method.getName())
                .requestId(UUID.randomUUID().toString())
                .url(url)
                .build();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(rpcRequest);
        if (url.isAsync()) {
            this.client.sendRequestAsync(rpcRequest);
            return null;
        }
        return this.client.sendRequest(rpcRequest);
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
    }
}
